#include "filehandler.h"
#include "constants.h"
#include <QDir>
#include <QStandardPaths>
#include <QCryptographicHash>
#include <QTemporaryFile>
#include <QJsonParseError>
#include <QCoreApplication>
#include <memory>

namespace RestaurantSystem {

// ============================================================================
// FileLock 实现
// ============================================================================

FileLock::FileLock(const QString& filePath) 
    : m_filePath(filePath)
    , m_lockFilePath(filePath + ".lock")
    , m_isLocked(false)
{
}

FileLock::~FileLock() {
    unlock();
}

bool FileLock::tryLock(int /*timeoutMs*/) {
    if (m_isLocked) {
        return true;
    }
    
    QFile lockFile(m_lockFilePath);
    
    // 检查锁文件是否已存在
    if (lockFile.exists()) {
        QFileInfo lockInfo(lockFile);
        // 如果锁文件超过10分钟，认为是死锁，强制删除
        if (lockInfo.lastModified().secsTo(QDateTime::currentDateTime()) > 600) {
            lockFile.remove();
        } else {
            return false; // 文件被其他进程锁定
        }
    }
    
    // 尝试创建锁文件
    if (lockFile.open(QIODevice::WriteOnly)) {
        QTextStream stream(&lockFile);
        stream << QDateTime::currentDateTime().toString(Qt::ISODate) << Qt::endl;
        stream << QCoreApplication::applicationPid() << Qt::endl;
        lockFile.close();
        m_isLocked = true;
        return true;
    }
    
    return false;
}

void FileLock::unlock() {
    if (m_isLocked) {
        QFile::remove(m_lockFilePath);
        m_isLocked = false;
    }
}

// ============================================================================
// FileHandler 实现
// ============================================================================

FileHandler::FileHandler(QObject* parent)
    : QObject(parent)
    , m_autoBackupEnabled(true)
    , m_maxBackupFiles(Constants::MAX_BACKUP_FILES)
    , m_maintenanceTimer(new QTimer(this))
{
    // 设置定期维护定时器
    m_maintenanceTimer->setInterval(60000); // 每分钟执行一次
    connect(m_maintenanceTimer, &QTimer::timeout, this, &FileHandler::onMaintenanceTimer);
    m_maintenanceTimer->start();
}

FileHandler::~FileHandler() = default;

FileOperationResult FileHandler::readJsonFile(const QString& filePath, QJsonObject& result) {
    if (!isFileReadable(filePath)) {
        LOG_ERROR("文件不可读", filePath);
        return FileOperationResult::FILE_NOT_FOUND;
    }
    
    FileLocker locker(filePath);
    if (!locker.isLocked()) {
        LOG_ERROR("无法获取文件锁", filePath);
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        LOG_ERROR("无法打开文件进行读取", filePath);
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    QByteArray data = file.readAll();
    file.close();
    
    QJsonParseError parseError;
    QJsonDocument document = QJsonDocument::fromJson(data, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        LOG_ERROR(QString("JSON解析错误: %1").arg(parseError.errorString()), filePath);
        return FileOperationResult::CORRUPTED_DATA;
    }
    
    if (!document.isObject()) {
        LOG_ERROR("JSON文档不是对象类型", filePath);
        return FileOperationResult::CORRUPTED_DATA;
    }
    
    result = document.object();
    return FileOperationResult::SUCCESS;
}

FileOperationResult FileHandler::writeJsonFile(const QString& filePath, const QJsonObject& data, bool createBackup) {
    // 确保目录存在
    QFileInfo fileInfo(filePath);
    if (!ensureDirectoryExists(fileInfo.absoluteDir().absolutePath())) {
        LOG_ERROR("无法创建目录", fileInfo.absoluteDir().absolutePath());
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    // 创建备份
    if (createBackup && m_autoBackupEnabled && QFile::exists(filePath)) {
        QString backupPath = this->createBackup(filePath);
        if (backupPath.isEmpty()) {
            LOG_WARNING("备份创建失败", filePath);
        }
    }
    
    FileLocker locker(filePath);
    if (!locker.isLocked()) {
        LOG_ERROR("无法获取文件锁", filePath);
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    QJsonDocument document(data);
    QByteArray jsonData = document.toJson(QJsonDocument::Indented);
    
    // 使用安全写入方式
    FileOperationResult result = safeWriteFile(filePath, jsonData);
    
    if (result == FileOperationResult::SUCCESS) {
        // 更新文件修改时间缓存
        QMutexLocker mutexLocker(&m_mutex);
        m_fileModificationTimes[filePath] = QDateTime::currentDateTime();
        
        // 清理旧备份
        if (m_autoBackupEnabled) {
            cleanupOldBackups(filePath, m_maxBackupFiles);
        }
    } else {
        LOG_ERROR("写入JSON文件失败", filePath);
    }
    
    return result;
}

FileOperationResult FileHandler::readJsonArray(const QString& filePath, QJsonArray& result) {
    QJsonObject obj;
    FileOperationResult opResult = readJsonFile(filePath, obj);
    
    if (opResult == FileOperationResult::SUCCESS) {
        // 假设数组存储在根对象的某个键下，或者整个文件就是数组
        if (obj.contains("data") && obj["data"].isArray()) {
            result = obj["data"].toArray();
        } else {
            // 如果文件直接是数组格式，重新读取
            QFile file(filePath);
            if (file.open(QIODevice::ReadOnly)) {
                QByteArray data = file.readAll();
                file.close();
                
                QJsonParseError parseError;
                QJsonDocument document = QJsonDocument::fromJson(data, &parseError);
                
                if (parseError.error == QJsonParseError::NoError && document.isArray()) {
                    result = document.array();
                } else {
                    return FileOperationResult::CORRUPTED_DATA;
                }
            }
        }
    }
    
    return opResult;
}

FileOperationResult FileHandler::writeJsonArray(const QString& filePath, const QJsonArray& data, bool createBackup) {
    // 将数组包装在对象中
    QJsonObject wrapper;
    wrapper["data"] = data;
    return writeJsonFile(filePath, wrapper, createBackup);
}

QString FileHandler::createBackup(const QString& filePath) {
    if (!QFile::exists(filePath)) {
        return QString();
    }
    
    QString backupPath = generateBackupPath(filePath);
    
    if (FileUtils::copyFile(filePath, backupPath)) {
        return backupPath;
    }
    
    return QString();
}

bool FileHandler::restoreBackup(const QString& filePath, const QString& backupPath) {
    if (!QFile::exists(backupPath)) {
        LOG_ERROR("备份文件不存在", backupPath);
        return false;
    }
    
    return FileUtils::copyFile(backupPath, filePath);
}

bool FileHandler::validateJsonFile(const QString& filePath, QString& errorString) {
    if (!isFileReadable(filePath)) {
        errorString = "文件不可读";
        return false;
    }
    
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        errorString = "无法打开文件";
        return false;
    }
    
    QByteArray data = file.readAll();
    file.close();
    
    QJsonParseError parseError;
    QJsonDocument::fromJson(data, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        errorString = parseError.errorString();
        return false;
    }
    
    errorString.clear();
    return true;
}

QFileInfo FileHandler::getFileInfo(const QString& filePath) {
    return QFileInfo(filePath);
}

bool FileHandler::ensureDirectoryExists(const QString& dirPath) {
    QDir dir;
    return dir.mkpath(dirPath);
}

void FileHandler::cleanupOldBackups(const QString& filePath, int maxBackups) {
    QStringList backups = getBackupFiles(filePath);
    
    // 删除超出数量限制的旧备份
    for (int i = maxBackups; i < backups.size(); ++i) {
        QFile::remove(backups[i]);
    }
}

QStringList FileHandler::getBackupFiles(const QString& filePath) {
    QFileInfo originalFile(filePath);
    QDir dir = originalFile.dir();
    QString baseName = originalFile.baseName();
    QString suffix = originalFile.suffix();
    
    // 查找备份文件模式: filename_20240101_120000.json.backup
    QString pattern = QString("%1_*.%2.backup").arg(baseName, suffix);
    QStringList filters;
    filters << pattern;
    
    QFileInfoList backupFiles = dir.entryInfoList(filters, QDir::Files, QDir::Time | QDir::Reversed);
    
    QStringList result;
    for (const QFileInfo& info : backupFiles) {
        result.append(info.absoluteFilePath());
    }
    
    return result;
}

bool FileHandler::isFileReadable(const QString& filePath) {
    QFileInfo info(filePath);
    return info.exists() && info.isReadable();
}

bool FileHandler::isFileWritable(const QString& filePath) {
    QFileInfo info(filePath);
    if (info.exists()) {
        return info.isWritable();
    } else {
        // 如果文件不存在，检查目录是否可写
        QDir dir = info.dir();
        return dir.exists() && QFileInfo(dir.absolutePath()).isWritable();
    }
}

qint64 FileHandler::getFileSize(const QString& filePath) {
    QFileInfo info(filePath);
    return info.exists() ? info.size() : -1;
}

void FileHandler::performMaintenance() {
    // 清理所有数据文件的旧备份
    QStringList dataFiles = {
        Constants::getUsersFilePath(),
        Constants::getMenuFilePath(),
        Constants::getOrdersFilePath(),
        Constants::getRatingsFilePath(),
        Constants::getConfigFilePath()
    };
    
    for (const QString& filePath : dataFiles) {
        if (QFile::exists(filePath)) {
            cleanupOldBackups(filePath, m_maxBackupFiles);
        }
    }
}

void FileHandler::onMaintenanceTimer() {
    performMaintenance();
}

QString FileHandler::generateBackupPath(const QString& originalPath) {
    QFileInfo info(originalPath);
    QString timestamp = QDateTime::currentDateTime().toString(Constants::BACKUP_DATE_FORMAT);
    
    return QString("%1/%2_%3.%4.backup")
        .arg(info.absoluteDir().absolutePath())
        .arg(info.baseName())
        .arg(timestamp)
        .arg(info.suffix());
}

FileOperationResult FileHandler::safeWriteFile(const QString& filePath, const QByteArray& data) {
    // 使用临时文件安全写入
    QFileInfo fileInfo(filePath);
    QTemporaryFile tempFile(fileInfo.absoluteDir().absoluteFilePath("temp_XXXXXX"));
    
    if (!tempFile.open()) {
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    qint64 written = tempFile.write(data);
    if (written != data.size()) {
        return FileOperationResult::DISK_FULL;
    }
    
    tempFile.flush();
    
    // 原子性地替换原文件
    QString tempPath = tempFile.fileName();
    tempFile.close(); // 关闭临时文件但不删除
    tempFile.setAutoRemove(false);
    
    if (QFile::exists(filePath)) {
        QFile::remove(filePath);
    }
    
    if (QFile::rename(tempPath, filePath)) {
        return FileOperationResult::SUCCESS;
    } else {
        // 清理临时文件
        QFile::remove(tempPath);
        return FileOperationResult::UNKNOWN_ERROR;
    }
}

// ============================================================================
// FileLocker 实现
// ============================================================================

FileLocker::FileLocker(const QString& filePath, int timeoutMs) {
    m_lock = std::make_unique<FileLock>(filePath);
    m_lock->tryLock(timeoutMs);
}

FileLocker::~FileLocker() = default;

// ============================================================================
// FileUtils 命名空间实现
// ============================================================================

namespace FileUtils {

QByteArray safeReadFile(const QString& filePath, FileOperationResult& result) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        result = QFile::exists(filePath) ? FileOperationResult::PERMISSION_DENIED : FileOperationResult::FILE_NOT_FOUND;
        return QByteArray();
    }
    
    QByteArray data = file.readAll();
    result = FileOperationResult::SUCCESS;
    return data;
}

FileOperationResult safeWriteFile(const QString& filePath, const QByteArray& data) {
    QFileInfo fileInfo(filePath);
    QDir dir = fileInfo.dir();
    
    if (!dir.exists() && !dir.mkpath(dir.absolutePath())) {
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        return FileOperationResult::PERMISSION_DENIED;
    }
    
    qint64 written = file.write(data);
    file.close();
    
    return (written == data.size()) ? FileOperationResult::SUCCESS : FileOperationResult::DISK_FULL;
}

bool createDirectory(const QString& dirPath) {
    QDir dir;
    return dir.mkpath(dirPath);
}

bool copyFile(const QString& sourcePath, const QString& destPath) {
    // 如果目标文件存在，先删除
    if (QFile::exists(destPath)) {
        QFile::remove(destPath);
    }
    
    return QFile::copy(sourcePath, destPath);
}

bool moveFile(const QString& sourcePath, const QString& destPath) {
    // 如果目标文件存在，先删除
    if (QFile::exists(destPath)) {
        QFile::remove(destPath);
    }
    
    return QFile::rename(sourcePath, destPath);
}

bool removeFile(const QString& filePath) {
    return QFile::remove(filePath);
}

QString getFileMD5(const QString& filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        return QString();
    }
    
    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(&file);
    
    return hash.result().toHex();
}

bool filesAreEqual(const QString& file1, const QString& file2) {
    QString hash1 = getFileMD5(file1);
    QString hash2 = getFileMD5(file2);
    
    return !hash1.isEmpty() && !hash2.isEmpty() && (hash1 == hash2);
}

} // namespace FileUtils

} // namespace RestaurantSystem
